/*!
 * Sketch (2013-11-24, 17:28)
 *
 * Copyright (C) 2011-2013 Hakim El Hattab, http://hakim.se
 */
window.sketch = {};

sketch.IO = function() {
    function e(e, t) {
        return e || 0 == e ? e : t;
    }
    var t = "/php/sketch.php";
    var o = "/php/sketch.php";
    var n = "/php/gallery.php";
    var a = "x";
    var i = null;
    
    return {
        initialize: function() {
            i = sketch.Main.linesToJSON();
        },
        hasUnsavedChanges: function() {
            return sketch.Main.linesToJSON() !== i;
        },
        saveSketch: function() {
            var e = sketch.Main.linesToJSON();
            this.hasUnsavedChanges() ? e.length > 255 ? (sketch.LoadingOverlay.show("Saving sketch", 100), $.post(t, "save=" + e, function(t) {
                sketch.LoadingOverlay.hide(), t.match(/error/gi) ? alert("Uh-oh, the server replied with a no-no :( Wait a minute and try again.") : (i = e, sketch.URL.writeID(t), sketch.Facebook.isConnected() && FB.api("/me/sketchtoy:draw", "post", {
                    sketch: sketch.Main.getSketchShareURL()
                }, function(e) {
                    !e || e.error;
                }), sketch.ShareOverlay.show(), sketch.Related.update())
            })) : alert("Please draw more before saving.") : sketch.ShareOverlay.show();
        },
        loadSketch: function(e, t) {
            $.get(o, {
                load: e
            }, function(e, o) {
                if (e.match(/error/gi)) 
                	alert("There was an error loading your sketch."), t("error", {});
                else {
                    i = e;
                    var o = "success";
                    try {
                        var n = sketch.IO.parseSketch($.parseJSON(e));
                    } catch (a) {
                        o = "error", alert("Uh-oh, an error occured while trying to load this sketch.")
                    }
                    t(o, n);
                }
            });
        },
        parseSketch: function(t) {
            for (var o = e(t.p, t.perspective), n = e(t.a, t.amplitude), i = e(t.l, t.lines), r = 0; i.length > r; r++) {
                i[r].color = e(i[r].c, "#000000");
                i[r].thickness = e(i[r].t, i[r].thickness);
                i[r].perspective = e(i[r].p, i[r].perspective);
                i[r].dashed = !!e(i[r].d, i[r].dashed);
                i[r].eraser = !!e(i[r].e, i[r].eraser);
                i[r].points = e(e(i[r].l, i[r].points), []);
                
                for (var s = i[r].points, c = 0; s.length > c; c++) {
                    var l = {
                        position: {
                            x: 0,
                            y: 0
                        },
                        normal: {
                            x: 0,
                            y: 0
                        }
                    };
                    "string" == typeof s[c] ? (l.position.x = parseFloat(s[c].slice(0, s[c].indexOf(a))), l.position.y = parseFloat(s[c].slice(s[c].indexOf(a) + 1))) : (l.position.x = s[c].x, l.position.y = s[c].y), l.normal.x = l.position.x, l.normal.y = l.position.y, s[c] = l
                }
            }
            for (var r = 0; i.length > r; r++) {
                var s = i[r].points;
                0 === s.length && (i.splice(r, 1), r--);
            }
            return {
                perspective: o,
                amplitude: n,
                lines: i
            };
        },
        loadGalleryItems: function(e, t, o, a) {
            $.get(n, {
                load: e,
                start: t,
                end: o
            }, function(e, t) {
                if (e.match(/error/gi)) 
                	alert("There was an error loading the sketches.");
                else {
                    var t = "success";
                    var o = 1;
                    var n = [];
                    try {
                        e = $.parseJSON(e);
                        o = e.totalRows;
                        for (var i = 0; e.sketches.length > i; i++) {
                            var r = r.IO.parseSketch(e.sketches[i].value);
                            r.id = e.sketches[i].id;
                            r.date = e.sketches[i].date;
                            r.views = e.sketches[i].views;
                            n.push(r);
                        }
                    } catch (s) {
                        t = "error";
                        alert("Uh-oh, an error occured while trying to load the sketches.");
                    }
                    a(t, n, o);
                }
            });
        }
    };
}();

sketch.URL = function() {
    function e() {
        return !(!window.history || !history.pushState);
    }
    var t = "";
    return {
        readID: function() {
            var e = window.location.pathname.split("/")[1];
            return t.length ? t : e.length ? e : window.location.hash.slice(1);
        },
        writeID: function(o) {
            t = o;
            e() && history.pushState({}, "Sketch Toy: " + o, "/" + o);
            var n = $('meta[property="og:url"]');
            0 === n.length && (n = $('<meta property="og:url" />'), n.appendTo($("head")));
            n.attr("content", sketch.Main.getSketchShareURL());
        }
    };
}();

sketch.Util = function() {
    return {
        hexToRGB: function(e) {
            return "string" == typeof e ? (e = e.split("#").join(""), {
                r: parseInt(e.slice(0, 2), 16),
                g: parseInt(e.slice(2, 4), 16),
                b: parseInt(e.slice(4, 6), 16)
            }) : {
                r: 0,
                g: 0,
                b: 0
            };
        },
        wrapNumber: function(e, t) {
            return e > t ? -t + e % t : -t > e ? t + e % t : e;
        },
        distanceBetween: function(e, t) {
            var o = e.x - t.x,
                n = e.y - t.y;
            return Math.sqrt(o * o + n * n);
        },
        supportsLocalStorage: function() {
            try {
                return localStorage.setItem("t", "t"), localStorage.removeItem("t"), true;
            } catch (e) {
                return false;
            }
        },
        isTouchDevice: function() {
            return !!navigator.userAgent.match(/ipod|ipad|iphone|android/gi);
        }
    };
}();

window.requestAnimFrame = function() {
    return window.requestAnimationFrame || window.webkitRequestAnimationFrame || window.mozRequestAnimationFrame || window.oRequestAnimationFrame || window.msRequestAnimationFrame || function(e) {
        window.setTimeout(e, 1e3 / 60);
    };
}();

sketch.Locale = function() {
    function e() {
        o();
        n();
        
        c.find("li").on("click", function(e) {
            var t = $(e.target).attr("data-language");
            "string" == typeof t && r[t] && sketch.Locale.change(t);
        });
        
        c.on("mouseenter", function() {
            c.find(".list").show();
        });
        
        c.on("mouseleave", function() {
            c.find(".list").hide();
        });
    }

    function t() {
        sketch.Util.supportsLocalStorage() && localStorage.setItem(a, s);
    }

    function o() {
        if (sketch.Util.supportsLocalStorage() && (s = localStorage.getItem(a), SketchConfig.autodetectLanguage && !s)) {
            var e = window.navigator.userLanguage || window.navigator.language;
            e && (e = e.slice(0, 2).toLowerCase(), r[e] && (sketch.Main.trackEvent("Locale", "Change Automatically", e, null, true), s = e, t()))
        }
        r[s] || (s = i);
    }

    function n() {
        var e = $(".toolbar");
        e.find(".new-button").text(sketch.Locale.string("new"));
        e.find(".save-button").text(sketch.Locale.string("save"));
        e.find(".undo-button").text(sketch.Locale.string("undo"));
        e.find(".eraser-toggle").text(sketch.Locale.string("erase"));
        e.find(".facebook-share .label").text(sketch.Locale.string("share"));
        e.find(".facebook-send .label").text(sketch.Locale.string("send"));
        e.find(".tweet-button .label").text(sketch.Locale.string("tweet"));
        e.find(".size-dropdown .dropdown-title .label").text(sketch.Locale.string("size") + ":");
        e.find(".color-dropdown .dropdown-title .label").text(sketch.Locale.string("color"));
        e.find(".color-dropdown .dropdown-title .label").text(sketch.Locale.string("color"));
        e.find(".vibration-dropdown .dropdown-title .label").text(sketch.Locale.string("vibration") + ":");
        
        var t = $(".share-overlay");
        t.find(".url .label").text(sketch.Locale.string("share-link") + ":");
        t.find(".share-facebook .label").text(sketch.Locale.string("share-fb"));
        t.find(".share-facebook-message .label").text(sketch.Locale.string("share-fb-message"));
        t.find(".share-facebook-photo .label").text(sketch.Locale.string("share-upload"));
        t.find(".share-email .label").text(sketch.Locale.string("share-email"));
        t.find(".share-twitter .label").text(sketch.Locale.string("share-tweet"));
        t.find(".share-download .label").text(sketch.Locale.string("share-download"));
        
        var o = $("footer");
        o.find(".links .terms").text(sketch.Locale.string("terms"));
        o.find(".links .privacy").text(sketch.Locale.string("privacy"));
        c.find(".button .label").text(sketch.Locale.string("language") + ":");
        c.find(".button .value").text(c.find(".list li[data-language=" + s + "]").text());
        c.removeClass("loading");
        
        var n = e.get(0);
        var a = e.css("display");
        
        n.style.display = "none";
        n.offsetHeight, n.style.display = a;
    }
    var a = "sketch-toy-language",
        i = "en",
        r = {
            en: {
                "new": "New",
                save: "Save",
                undo: "Undo",
                erase: "Erase",
                size: "Size",
                vibration: "Vibration",
                color: "Color",
                show: "Show",
                hide: "Hide",
                remove: "Remove",
                share: "Share",
                send: "Send",
                tweet: "Tweet",
                "share-link": "Link",
                "share-fb": "Share",
                "share-fb-message": "Send Message",
                "share-tweet": "Tweet",
                "share-email": "Email",
                "share-upload": "Upload Image",
                "share-download": "Download Image",
                "featured-sketches": "Featured Sketches",
                comments: "Comments",
                "connect-fb": "Connect With Facebook",
                language: "Language",
                terms: "Terms of Service",
                privacy: "Privacy",
                "promotion-title": "Sketch Toy",
                "promotion-body": "Sketch using animated lines and share replays with friends!",
                "sketch-fb": "An animated sketch! Click to replay.",
                "sketch-tweet": "Check out this drawing!",
                "alert-unsaved-statement": "The current drawing will be lost",
                "alert-unsaved-confirmation": "The current drawing will be lost, do you want to continue?"
            },
            pt: {
                "new": "Novo",
                save: "Salvar",
                undo: "Apagar",
                erase: "Desfazer",
                size: "Tamanho",
                vibration: "Vibra챌찾o",
                color: "Cor",
                show: "Mostrar",
                hide: "Esconder",
                remove: "Remover",
                share: "Compartilhar",
                send: "Enviar",
                tweet: "Tuitar",
                "share-link": "Link",
                "share-fb": "Compartilhar",
                "share-fb-message": "Enviar Mensagem",
                "share-tweet": "Tuitar",
                "share-email": "Enviar Email",
                "share-upload": "Upload de Imagem",
                "share-download": "Download da Imagem",
                "featured-sketches": "Desenhos em destaque",
                comments: "Coment찼rios",
                "connect-fb": "Conectar com Facebook",
                language: "L챠ngua",
                terms: "Termos de Servi챌o",
                privacy: "Privacidade",
                "promotion-title": "Sketch Toy",
                "promotion-body": "Fa챌a desenhos e compartilhe o replay com amigos",
                "sketch-fb": "Um desenho animado! Clique para assistir o replay.",
                "sketch-tweet": "Olhe esse desenho!",
                "alert-unsaved-statement": "O desenho atual ser찼 perdido.",
                "alert-unsaved-confirmation": "O desenho atual ser찼 perdido, quer continuar?"
            },
            es: {
                "new": "Nuevo",
                save: "Guardar",
                undo: "Deshacer",
                erase: "Borrar",
                size: "Tama챰o",
                vibration: "Vibraci처n",
                color: "Color",
                show: "Mostrar",
                hide: "Ocultar",
                remove: "Eliminar",
                share: "Compartir",
                send: "Enviar",
                tweet: "Tweet",
                "share-link": "Enlace",
                "share-fb": "Compartir",
                "share-fb-message": "Enviar mensajee",
                "share-tweet": "Tweet",
                "share-email": "Email",
                "share-upload": "Subir imagene",
                "share-download": "Descargar Imagene",
                "featured-sketches": "Bocetos destacados",
                comments: "Comentarios",
                "connect-fb": "Con챕ctate con Facebook",
                language: "Idioma",
                terms: "T챕rminos de Servicio",
                privacy: "Privacidad",
                "promotion-title": "Sketch Toy",
                "promotion-body": "Dibuja bocetos y compartir repeticiones con amigos",
                "sketch-fb": "Un dibujo animado! Haz clic aqu챠 para reproducir.",
                "sketch-tweet": "Echa un vistazo a este dibujo!",
                "alert-unsaved-statement": "Se perder찼 el dibujo actual",
                "alert-unsaved-confirmation": "Se perder찼 el dibujo actual, 쩔desea continuar?"
            },
            tr: {
                "new": "Yeni",
                save: "Kaydet",
                undo: "Geri Al",
                erase: "Sil",
                size: "Boyut",
                vibration: "Titre힊im",
                color: "Renk",
                show: "G철ster",
                hide: "Gizle",
                remove: "Kald캇r",
                share: "Payla힊",
                send: "Mesaj",
                tweet: "Tweet At",
                "share-link": "Ba휓lant캇",
                "share-fb": "Payla힊",
                "share-fb-message": "Mesaj G철nder",
                "share-tweet": "Tweet At",
                "share-email": "E-posta",
                "share-upload": "Resim Y체kle",
                "share-download": "Resmi 캅ndir",
                "featured-sketches": "횜ne 챌캇kan 챌izimler",
                comments: "Yorumlar",
                "connect-fb": "Facebook ile Ba휓lan",
                language: "Dil",
                terms: "Hizmet 힇artlar캇",
                privacy: "Gizlilik",
                "promotion-title": "Sketch Toy",
                "promotion-body": "횉izim yap캇n ve arkada힊lar캇n캇zla payla힊캇n.",
                "sketch-fb": "Hareketli bir 챌izim! 캅zlemek i챌in t캇klay캇n.",
                "sketch-tweet": "힇u 챌izime bak캇n!",
                "alert-unsaved-statement": "Ge챌erli 챌izim kaybolacak.",
                "alert-unsaved-confirmation": "Ge챌erli 챌izim kaybolacak. Devam etmek istiyor musunuz?"
            }
        },
        s = i,
        c = $(".select-language");
    return {
        initialize: e,
        string: function(e) {
            var t = r[s] || t[i];
            var o = t[e];
            return o === void 0 && (o = r[i][e]), o === void 0 && (o = ""), o;
        },
        change: function(e) {
            r[e] && (sketch.Main.trackEvent("Locale", "Change", e), s = e, t(), window.location.reload());
        }
    };
}();

sketch.Social = function() {
    function e() {
        a || sketch.Util.isTouchDevice() || (a = true, t(), o());
    }

    function t() {
        $.ajax({
            url: "//platform.twitter.com/widgets.js",
            type: "GET",
            dataType: "script"
        });
    }

    function o() {};

    function n(e, t, o, n) {
        var a = "https://twitter.com/intent/tweet?url=" + encodeURIComponent(e) + "&text=" + encodeURIComponent(t) + "&related=sketchtoy";
        n && (a += "&via=" + n);
        o && (a += "&hashtags=" + o);
        var i = 550,
            r = 420,
            s = Math.round(screen.width / 2 - i / 2);
        y = 0;
        screen.height > r && (y = Math.round(screen.height / 2 - r / 2));
        window.open(a, "twitter_share", "height=" + r + ", width=" + i + ", left=" + s + ", top=" + y + ", toolbar=no, menubar=no, scrollbars=no, resizable=no, location=no, directories=no, status=no");
    }
    
    var a = false;
    
    return {
        initialize: e,
        tweet: n
    };
}();

sketch.Related = function() {
    function e() {
        i = $(".related");
        r = $(".related-gallery");
        s = $(".related-comments");
        c || sketch.Util.isTouchDevice() || (c = true, "/" !== window.location.pathname ? (n(), t()) : t("horizontal"));
    }

    function t(e) {
        r.length && (r.addClass(e), $.ajax({
            url: "http://sketch-toy.tumblr.com/api/read/json?callback=?",
            dataType: "script",
            context: this,
            success: function() {
                "object" == typeof tumblr_api_read && tumblr_api_read.posts.length && o(tumblr_api_read.posts);
            }
        }));
    }

    function o(e) {
        if (e && r.length) {
            $("<h3>").text(sketch.Locale.string("featured-sketches") + ":").appendTo(r);
            for (var t = "/" === window.location.pathname ? 6 : 4, o = 0, n = Math.min(e.length, t); n > o; o++) {
                var a = e[o];
                $(['<a href="' + a["photo-link-url"] + '">', '<img src="' + a["photo-url-250"] + '">', "</a>"].join("")).appendTo(r);
            }
        }
    }

    function n() {
        s.length && (s.empty().append("<h3>" + sketch.Locale.string("comments") + ":</h3>", '<div class="fb-comments" data-href="' + sketch.Main.getSketchShareURL() + '" data-width="500" data-num-posts="3"></div>'), s.addClass("visible"), FB.XFBML.parse(s.get(0)));
    }

    function a() {
        c && "/" !== window.location.pathname && n();
    }
    var i, r, s, c = false;
    return {
        initialize: e,
        update: a
    };
}();

sketch.Dropdown = {
    create: function(e) {
        function t() {
            d.addClass("open");
            u.addClass("open");
            $(document).on("mousedown", h);
        }

        function o() {
            d.removeClass("open");
            u.removeClass("open");
            $(document).off("mousedown", h);
        }

        function n(e) {
            f = e;
            d.find(".value").text(e);
            u.find("button").removeClass("selected");
            u.find('button[data-value="' + f + '"]').addClass("selected");
        }

        function a() {
            return f;
        }

        function i(e) {
            e.preventDefault();
        }

        function r(e) {
            e.preventDefault();
        }

        function s(e) {
            e.preventDefault();
            var t = $(e.currentTarget);
            t.length && (n(t.attr("data-value")), o(), "function" == typeof this.onChanged && this.onChanged(f));
        }

        function c() {
            u.hasClass("auto-width") && u.width(d.outerWidth() - 1);
            t();
        }

        function l() {
            o();
        }

        function h(t) {
            for (var n = t.target, a = true; n && n.getAttribute;) {
                if (n && n == e.get(0)) {
                    a = false;
                    break
                }
                n = n.parentNode;
            }
            a && o();
        }
        var d = e.find(".dropdown-title");
        var u = e.find(".dropdown-list");
        var p = u.find("button");
        var f = null;
        
        e.on("mouseover", $.proxy(c, this));
        e.on("mouseout", $.proxy(l, this));
        
        d.on("click", $.proxy(i, this));
        d.on("mousedown", $.proxy(r, this));
        
        p.on("click", $.proxy(s, this));
        
        this.setValue = n;
        this.getValue = a;
    }
};

sketch.Facebook = function() {
    function e() {
        v = $(".facebook-send");
        m = $(".facebook-share");
        
        $facebookInvite = $(".facebook-invite");
        w = $(".facebook-connect");
        
        $facebookContents = $(".facebook-connect .contents");
        v.on("click", d);
        m.on("click", h);
        
        $facebookInvite.on("click", u);
        w.on("click", p);
        
        FB.getLoginStatus(function(e) {
            e && "connected" === e.status ? n(null, true) : i(false);
        });
    }

    function t(e, t) {
        e = e || function() {};
        FB.getLoginStatus(function(o) {
            "connected" !== o.status || t ? FB.login(function(t) {
                t.authResponse ? e.call(null, true) : e.call(null, false)
            }, t) : e.call(null, true);
        });
    }

    function o(e, t) {
        t = t || function() {};
        FB.api("/me/permissions", function(o) {
            o && o.data && o.data.length && o.data[0][e] ? t.call(null, true) : t.call(null, false);
        });
    }

    function n(e, t) {
        e = e || function() {};
        o("publish_actions", function(o) {
            o ? (i(true), e.call(null, true)) : t ? (i(false), e.call(null, false)) : FB.login(function(t) {
                t.authResponse ? n(null, true) : (i(false), e.call(null, false));
            }, {
                scope: "publish_actions"
            });
        });
    }

    function a(e) {
        k && k.id && FB.api(k.id + "/permissions?permission=publish_actions", "delete", {}, function(t) {
            !t || t.error ? e.call(null, false) : e.call(null, true);
        });
    }

    function i(e) {
        b = e;
        $facebookContents.empty();
        b ? FB.api("/me", {
            fields: "id,name,first_name,picture"
        }, function(e) {
            if (e) {
                k = e;
                var t = $('<div class="title">').text("Hello " + e.first_name + "!").appendTo($facebookContents);
                e.picture && e.picture.data && $('<img class="avatar">').attr({
                    src: e.picture.data.url,
                    height: 26
                }).prependTo(t);
                var o = $('<div class="dropdown">').appendTo($facebookContents);
                $("<p>").text("Sketches you save are automatically published to your Facebook stream.").appendTo(o);
                $('<a href="#">').text("Disconnect?").appendTo(o).on("click", f);
            }
            w.removeClass("loading").addClass("connected");
        }) : w.removeClass("loading").removeClass("connected");
    }

    function r(e, t, o) {
        FB.ui({
            method: "send",
            name: t,
            link: e,
            description: o
        });
    }

    function s(e, t, o) {
        FB.ui({
            method: "feed",
            name: t,
            link: e,
            description: o
        });
    }

    function c() {
        function e() {
            g && g.abort();
            
            var e = new FormData;
            e.append("file", i);
            e.append("access_token", FB.getAccessToken());
            e.append("message", "Replay: " + sketch.Main.getSketchShareURL());
            
            g = $.ajax({
                url: "https://graph.facebook.com/me/photos",
                data: e,
                type: "POST",
                cache: false,
                contentType: false,
                processData: false,
                timeout: 3e4,
                statusCode: {
                    400: function() {
                        a();
                    },
                    401: function() {
                        a();
                    },
                    403: function() {
                        a();
                    },
                    500: function() {
                        a();
                    }
                },
                complete: function(e, t) {
                    var o;
                    try {
                        o = $.parseJSON(e.responseText);
                    } catch (i) {
                        a(t);
                    }
                    o && 0 === o.success ? a() : "OK" === e.statusText && o && o.id ? n() : a();
                }
            });
        }

        function n() {
            sketch.LoadingOverlay.hideSuccess("Photo uploaded!");
            sketch.Main.trackEvent("Facebook", "Photo Upload Success");
        }

        function a() {
            sketch.LoadingOverlay.hideError("Failed to upload photo");
            sketch.Main.trackEvent("Facebook", "Photo Upload Error");
        }
        sketch.LoadingOverlay.show("Uploading photo...");
        
        var i = sketch.Main.getSketchAsBlob();
        i && o("publish_actions", function(o) {
            o && FB.getAccessToken() ? e() : t(function(t) {
                t ? e() : (sketch.LoadingOverlay.hide(), sketch.Main.trackEvent("Facebook", "Photo Upload Cancel"));
            }, {
                scope: "publish_actions"
            });
        });
    }

    function l() {
        return b;
    }

    function h(e) {
        sketch.URL.readID() ? sketch.Facebook.share(sketch.Main.getSketchShareURL(), sketch.Locale.string("promotion-title"), sketch.Locale.string("promotion-body")) : sketch.Facebook.share(window.location.protocol + "//" + window.location.host + "/", sketch.Locale.string("promotion-title"), sketch.Locale.string("promotion-body")), sketch.Main.trackEvent("Toolbar", "Facebook Share"), e.preventDefault()
    }

    function d(e) {
        sketch.URL.readID() ? sketch.Facebook.send(sketch.Main.getSketchShareURL(), sketch.Locale.string("sketch-fb"), sketch.Locale.string("promotion-body")) : sketch.Facebook.send(window.location.protocol + "//" + window.location.host + "/", sketch.Locale.string("promotion-title"), sketch.Locale.string("promotion-body")), sketch.Main.trackEvent("Toolbar", "Facebook Send"), e.preventDefault()
    }

    function u(e) {
        FB.ui({
            method: "apprequests",
            message: "Sketch with me",
            filters: []
        }, function(e) {
            return e && e.to ? (sketch.Main.trackEvent("Header", "Facebook Invite Sent"), void 0) : (sketch.Main.trackEvent("Header", "Facebook Invite Cancel"), false);
        });
        
        sketch.Main.trackEvent("Header", "Facebook Invite");
        e.preventDefault();
    }

    function p(e) {
        w.hasClass("loading") || w.hasClass("connected") || (l() || sketch.Facebook.login(function(e) {
            e ? n(null, true) : i(false)
        }, {
            scope: "publish_actions"
        }), sketch.Main.trackEvent("Header", "Facebook Connect")), e.preventDefault()
    }

    function f(e) {
        a(function(e) {
            e && i(false);
        });
        
        sketch.Main.trackEvent("Header", "Facebook Disconnect");
        e.preventDefault();
    }
    
    var k, g, v, m, w, b = false;
    
    return {
        initialize: e,
        login: t,
        send: r,
        share: s,
        upload: c,
        connect: n,
        isConnected: l
    };
}();

sketch.ShareOverlay = function() {
    function e() {
        u.val(sketch.Main.getSketchShareURL());
        var e = encodeURIComponent("An animated sketch"),
            t = encodeURIComponent("Check out this sketch: " + sketch.Main.getSketchShareURL());
        p.attr("href", "mailto:?body=" + t + "&subject=" + e);
        var o = d.find(".share-download");
        o.length && o.get(0).download !== void 0 && d.find(".share-download").off().attr({
            href: sketch.Main.getSketchAsImage(),
            download: "sketch-" + sketch.URL.readID() + ".png",
            target: ""
        });
    }

    function t(e) {
        e.preventDefault();
        sketch.ShareOverlay.hide();
    }

    function o(e) {
        e.target === d.get(0) && (e.preventDefault(), sketch.ShareOverlay.hide());
    }

    function n(e) {
        e.preventDefault();
        u.select();
    }

    function a(e) {
        e.preventDefault();
        sketch.Facebook.share(sketch.Main.getSketchShareURL(), k);
        sketch.Main.trackEvent("Share", "Facebook");
    }

    function i(e) {
        e.preventDefault();
        sketch.Facebook.send(sketch.Main.getSketchShareURL(), k);
        sketch.Main.trackEvent("Share", "Facebook Message");
    }

    function r(e) {
        e.preventDefault();
        sketch.Facebook.upload();
        sketch.Main.trackEvent("Share", "Facebook Photo");
    }

    function s(e) {
        e.preventDefault();
        sketch.Social.tweet(sketch.Main.getSketchShareURL(), f, "sketchtoy", "sketchtoy");
        sketch.Main.trackEvent("Share", "Twitter");
    }

    function c() {
        sketch.Main.trackEvent("Share", "Email");
    }

    function l(e) {
        e.preventDefault();
        sketch.Main.saveSketchAsImage();
        sketch.Main.trackEvent("Share", "Download");
    }

    function h(e) {
        27 === e.keyCode && (e.preventDefault(), sketch.ShareOverlay.hide());
    }
    
    var d = $(".share-overlay");
    u = d.find(".url input");
    p = d.find(".share-email");
    f = "";
    k = "";
    
    d.find(".close").on("click", t);
    d.find(".share-facebook").on("click", a);
    d.find(".share-facebook-message").on("click", i);
    d.find(".share-facebook-photo").on("click", r);
    d.find(".share-twitter").on("click", s);
    d.find(".share-email").on("click", c);
    d.find(".share-download").on("click", l);
    d.on("click", o);
    
    u.on("click", n);
    
    return {
        show: function() {
            d.toggleClass("empty", sketch.Main.isEmpty());
            d.show();
            sketch.Main.isEmpty() ? (k = sketch.Locale.string("promotion-title"), f = sketch.Locale.string("promotion-body")) : (k = sketch.Locale.string("sketch-fb"), f = sketch.Locale.string("sketch-tweet"));
            e();
            u.select();
            $(document).on("keydown", h);
        },
        hide: function() {
            d.hide();
            $(document).off("keydown", h);
        }
    };
}();

sketch.LoadingOverlay = function() {
    var e = $(".loading-overlay");
    e.find(".status");
    loadingMessage = e.find(".message");
    timeout = -1;
    
    return {
        show: function(t, o) {
            clearTimeout(timeout);
            "number" == typeof o ? timeout = setTimeout(function() {
                sketch.LoadingOverlay.show(t);
            }, o) : (e.addClass("visible"), e.removeClass("success-state error-state").addClass("loading-state"), loadingMessage.text(t || ""));
        },
        hide: function() {
            clearTimeout(timeout);
            e.removeClass("visible");
        },
        hideSuccess: function(t) {
            e.removeClass("loading-state error-state").addClass("success-state");
            loadingMessage.text(t || "");
            clearTimeout(timeout);
            timeout = setTimeout(sketch.LoadingOverlay.hide, 2e3);
        },
        hideError: function(t) {
            e.removeClass("success-state loading-state").addClass("error-state");
            loadingMessage.text(t || "");
            clearTimeout(timeout);
            timeout = setTimeout(sketch.LoadingOverlay.hide, 3e3);
        }
    };
}();

sketch.Main = function() {
    function e(e) {
        $(document.body).addClass("loading");
        sketch.IO.loadSketch(e, function(e, t) {
            $(document.body).removeClass("loading"), "success" === e ? Z.injectSketch(t) : gt = [];
        });
    }

    function t(e) {
        replayProgressBefore = wt || 0, wt = Math.max(0, Math.min(e, 1));
        var t = Math.ceil(wt * mt),
            o = 0;
        r();
        gt = [];
        e: for (var n = 0, a = vt.length; a > n; n++) {
            var i = gt[n] = gt[n] || {
                color: vt[n].color,
                thickness: vt[n].thickness,
                perspective: vt[n].perspective,
                dashed: vt[n].dashed,
                eraser: vt[n].eraser,
                points: []
            };
            St = i.perspective;
            var s = vt[n].points.concat();
            if (t > o + s.length) o += s.length, i.points = s;
            else 
            {
                for (var c = 0, l = s.length; l > c; c++) {
                    var h = s[c];
                    if (i.points.push(h), o++ > t) 
                    	break e;
                }
            }
        }
        1 === wt && (St = Dt);
    }

    function o() {
        xt = true;
        $("html").addClass("replaying");
        clearInterval(bt);
        bt = setInterval(function() {
            var e = dt;
            mt > 3e4 ? e *= 2 : mt > 15e3 && (e *= 1.5);
            var o = Math.ceil(wt * mt) + e;
            t(o / mt);
        }, ht);
    }

    function n() {
        clearInterval(bt);
    }

    function a() {
        o();
    }

    function i() {
        $("html").removeClass("replaying");
        clearInterval(bt);
        xt && (xt = false, wt = 1, gt = vt, Mt = Dt, St = Dt, v());
    }

    function r() {
        At.replayControlsProgress.css("width", 100 * wt + "%");
    }

    function s() {
        if (!navigator.userAgent.match(/ipod|ipad|iphone|android/gi)) {
            var e = false;
            try {
                e = "localStorage" in window && null !== window.localStorage;
            } catch (t) {
                e = false;
            }
        }
    }

    function c() {
        colorDropdown = new sketch.Dropdown.create($(".color-dropdown"));
        colorDropdown.setValue(Tt);
        colorDropdown.onChanged = function(e) {
            l(e);
            Z.trackEvent("Toolbar", "Color", e);
        };
        
        sizeDropdown = new sketch.Dropdown.create($(".size-dropdown"));
        sizeDropdown.setValue($t);
        sizeDropdown.onChanged = function(e) {
            Z.trackEvent("Toolbar", "Size", e);
        };
        
        vibrationDropdown = new sketch.Dropdown.create($(".vibration-dropdown"));
        vibrationDropdown.setValue(1);
        vibrationDropdown.onChanged = function(e) {
            Lt = nt * e;
            Z.trackEvent("Toolbar", "Vibration", e);
        }
    }

    function l(e) {
        var t = $(".color-dropdown .dropdown-title");
        var o = sketch.Util.hexToRGB(e);
        t.toggleClass("light", o.r + o.g > 500 || o.r + o.b > 500 || o.b + o.g > 500), t.css({
            "background-color": e,
            "box-shadow": "2px 2px 1px rgba(" + o.r + "," + o.g + "," + o.b + ",0.4)"
        })
    }

    function h() {
        Ft = K.offset();
        Ft.left -= $(window).scrollLeft();
        Ft.top -= $(window).scrollTop();
    }

    function d(e) {
        u();
        var t = $('<div class="stencil" style="background-image: url(' + e + ')">').appendTo(Q),
            o = $('<div class="stencil-controls">').text("Background image: ").appendTo(Q),
            n = $('<a class="stencil-button toggle" href="#">' + sketch.Locale.string("hide") + "</a>").appendTo(o),
            a = $('<a class="stencil-button clear" href="#">' + sketch.Locale.string("remove") + "</a>").appendTo(o);
        
        setTimeout(function() {
            t.addClass("visible")
        }, 200);
        
        n.on("click", function(e) {
            e.preventDefault();
            t.toggleClass("visible");
            n.text(t.hasClass("visible") ? sketch.Locale.string("hide") : sketch.Locale.string("show"));
        });
        
        a.on("click", function(e) {
            e.preventDefault();
            u();
        });
        
        $("html").addClass("has-stencil");
    }

    function u() {
        Q.find(".stencil, .stencil-controls").remove();
        $("html").removeClass("has-stencil");
    }

    function p(e) {
        It.press.x = It.x;
        It.press.y = It.y;
        e.target == W && (xt && i(), $t = sizeDropdown.getValue() || it, Tt = colorDropdown.getValue() || rt, gt.push({
            color: Tt,
            thickness: $t,
            perspective: Mt,
            dashed: Bt,
            eraser: zt,
            points: []
        }), e.preventDefault(), Ot === false && (Ot = true, sketch.Main.trackEvent("Canvas", "Drew First Line")));
    }

    function f(e, t, o, n, a) {
        for (var i = Math.round(Math.random() * o); i--;) 
        	kt.push({
            position: {
                x: e,
                y: t
            },
            velocity: {
                x: .5 * Math.random() - .25,
                y: 3 * Math.random()
            },
            alpha: .98,
            perspective: n,
            color: a || "#000000"
        })
    }

    function k() {
        At.eraserToggle.toggleClass("on");
        zt = At.eraserToggle.hasClass("on");
    }

    function g() {
        requestAnimFrame(g);
        v();
    }

    function v() {
        X.clearRect(0, 0, W.width, W.height);
        X.save();
        X.scale(pt.scale, pt.scale);
        m();
        w();
        X.restore();
    }

    function m() {
        var e = 999;
        var t = gt[gt.length - 1];
        
        if (t) {
            var o = t.points[t.points.length - 1];
            o && (e = sketch.Util.distanceBetween(It, o.position));
        }
        xt && (Mt += .08 * (St - Mt));
        Mt = sketch.Util.wrapNumber(Mt + Et, 1);
        Et *= .8;
        (Rt.spaceDown || Rt.leftDown || Rt.rightDown) && (Ut = 1);
        It.down && Rt.spaceDown ? Et += It.diff.x / pt.width : Rt.leftDown && !Rt.rightDown ? Et -= .005 : Rt.rightDown && !Rt.leftDown ? Et += .005 : It.down && Math.abs(e) > lt && (t.points.push({
            position: {
                x: It.x,
                y: It.y
            },
            normal: {
                x: It.x,
                y: It.y
            }
        }), yt++, zt || f(It.x, It.y, 5, Mt, Tt)), It.diff.x = 0, It.diff.y = 0
    }

    function w() {
    	
        for (var e = gt.length, t = 0; e > t; t++) {
            var o = gt[t];
            n = o.color || "#000000";
            a = o.thickness;
            i = sketch.Util.wrapNumber(2 * (Mt - o.perspective), 2);
            r = o.dashed;
            s = o.eraser;
            c = o.points;
            l = c.length;
            h = c[0],
            d = c[1];
            
            if (s && (X.save(), X.globalCompositeOperation = "destination-out"), l > 1) {
                r || X.beginPath();
                for (var u = 1, p = c.length; p > u; u++) {
                    r && X.beginPath();
                    1 > sketch.Util.distanceBetween(h.position, h.normal) && (h.position.x += (Math.random() - .5) * Lt, h.position.y += (Math.random() - .5) * Lt);
                    h.position.x += (h.normal.x - h.position.x) * Ct, h.position.y += (h.normal.y - h.position.y) * Ct;
                    
                    var f = h.position.x,
                    	k = d.position.x;
                    f += i * (h.position.x - .5 * tt) * (0 > i ? 1 : -1);
                    k += i * (d.position.x - .5 * tt) * (0 > i ? 1 : -1);
                    (1 == u || r) && X.moveTo(f, h.position.y);
                    X.quadraticCurveTo(f, h.position.y, f + (k - f) / 2, h.position.y + (d.position.y - h.position.y) / 2);
                    h = c[u];
                    d = c[u + 1];
                    r && b(a, n);
                }
                r || (b(a, n), X.closePath());
            } else 1 === l && (h.position.x += (Math.random() - .5) * Lt, h.position.y += (Math.random() - .5) * Lt, h.position.x += (h.normal.x - h.position.x) * Ct, h.position.y += (h.normal.y - h.position.y) * Ct, y(h.position.x + i * (h.position.x - .5 * tt) * (0 > i ? 1 : -1), h.position.y, a / 2, n));
            s && X.restore();
        }
        
        for (var u = 0; kt.length > u; u++) {
            var g = kt[u];
            i = sketch.Util.wrapNumber(2 * (Mt - g.perspective), 2);
            g.position.x += g.velocity.x;
            g.position.y += g.velocity.y;
            
            var v = g.position.x;
            v += i * (g.position.x - .5 * pt.width) * (0 > i ? 1 : -1);
            g.alpha *= .94;
            var m = {
                r: 0,
                g: 0,
                b: 0
            };
            g.color && (m = sketch.Util.hexToRGB(g.color));
            
            X.fillStyle = "rgba(" + m.r + "," + m.g + "," + m.b + "," + g.alpha + ")";
            X.fillRect(v, g.position.y, 1, 1);
            .05 > g.alpha && (kt.splice(u, 1), u--);
        }
        
        if (Ut > 0) {
            X.save();
            X.globalAlpha = Math.max(Ut, 0);
            X.beginPath();
            X.scale(1, .5);
            
            for (var w = Mt * Math.PI - Math.PI / 2, u = 0; 2 > u; u++) {
                var x = 0 == u ? ct : 0;
                X.moveTo(tt / 2, 1.7 * ot + 2);
                X.arc(tt / 2, 1.7 * ot + x, st, w - .2, w + .2, true);
                X.closePath();
                X.lineWidth = 4;
                X.strokeStyle = "rgb(165,106,70)";
                X.stroke();
                X.fillStyle = "rgba(240,150,105,0.85)";
                X.fill();
                X.beginPath();
            }
            X.restore();
            Ut -= .05;
        }
        
        if (It.over) {
            var m = sketch.Util.hexToRGB(zt ? "#000000" : colorDropdown.getValue() || rt);
            X.beginPath();
            X.arc(It.x, It.y, (sizeDropdown.getValue() || it) / 2, 0, 2 * Math.PI, true);
            X.closePath();
            X.fillStyle = "rgba(" + m.r + "," + m.g + "," + m.b + ",0.4)";
            X.fill();
        }
    }

    function b(e, t) {
        X.lineCap = "round";
        X.lineJoin = "round";
        X.lineWidth = e;
        X.strokeStyle = t;
        X.stroke();
    }
    
    function y(e, t, o, n) {
        X.beginPath();
        X.arc(e, t, o, 0, 2 * Math.PI, true);
        X.fillStyle = n;
        X.fill();
        X.closePath();
    }

    function x(e) {
        e.preventDefault();
        Z.saveSketch();
        Z.trackEvent("Toolbar", "Save/Share");
    }

    function S(e) {
        e.preventDefault();
        xt && i();
        gt.length ? Z.saveSketch() : sketch.ShareOverlay.show();
        Z.trackEvent("Toolbar", "Share");
    }

    function D(e) {
        e.preventDefault();
        xt && i();
        gt.pop();
        Z.trackEvent("Toolbar", "Undo");
    }

    function L(e) {
        (!sketch.IO.hasUnsavedChanges() || confirm(sketch.Locale.string("alert-unsaved-confirmation"))) && (gt.length > 0, mt = 0, wt = 0, vt = [], gt = [], kt = [], sketch.URL.writeID(""), yt = 0, Z.trackEvent("Toolbar", "Reset")), e.preventDefault()
    }

    function C(e) {
        if (!sketch.IO.hasUnsavedChanges() || confirm(sketch.Locale.string("alert-unsaved-confirmation"))) {
            var t = gt.length > 0;
            mt = 0;
            wt = 0;
            vt = [];
            gt = [];
            kt = [];
            sketch.URL.writeID("");
            yt = 0;
            Z.trackEvent("Toolbar", "New");
            t && (window.location = "/");
        }
        e.preventDefault();
    }

    function T(e) {
        At.dashToggle.toggleClass("on");
        Bt = At.dashToggle.hasClass("on");
        Z.trackEvent("Toolbar", "Dash", Bt ? 1 : 0);
        e.preventDefault();
    }

    function M(e) {
        k();
        Z.trackEvent("Toolbar", "Eraser", zt ? 1 : 0);
        e.preventDefault();
    }

    function E(e) {
        e.preventDefault();
        sketch.Social.tweet(sketch.Main.getSketchShareURL(), sketch.Locale.string("sketch-tweet"), "sketchtoy");
        sketch.Main.trackEvent("Toolbar", "Tweet");
    }

    function U(e) {
        var t = true;
        switch (e.keyCode) {
            // Space
            case 32:
                Rt.spaceDown = true;
                break;
            // Left Arrow
            case 37:
                Rt.leftDown = true;
                break;
            // Right Arrow
            case 39:
                Rt.rightDown = true;
                break;
            // E Button
            case 69:
                k();
                break;
            // Z Button
            case 90:
                (e.ctrlKey || e.metaKey) && gt.pop();
                break;
            default:
                t = false
        }
        t && (e.preventDefault(), xt && i());
    }

    function F(e) {
        switch (e.keyCode) {
        	// Space
            case 32:
                Rt.spaceDown = false;
                e.preventDefault();
                break;
            // Left Arrow
            case 37:
                Rt.leftDown = false;
                e.preventDefault();
                break;
            // Right Arrow
            case 39:
                Rt.rightDown = false;
                e.preventDefault();
        }
    }

    function I(e) {
        It.down = true;
        h();
        It.x = (e.clientX - Ft.left) / pt.scale;
        It.y = (e.clientY - Ft.top) / pt.scale;
        p(e);
    }

    function R(e) {
        It.over && h();
        It.prev.x = It.x;
        It.prev.y = It.y;
        It.x = (e.clientX - Ft.left) / pt.scale;
        It.y = (e.clientY - Ft.top) / pt.scale;
        It.diff.x = It.x - It.prev.x;
        It.diff.y = It.y - It.prev.y;
    }

    function B(e) {
        It.down = false;
        It.x = (e.clientX - Ft.left) / pt.scale;
        It.y = (e.clientY - Ft.top) / pt.scale;
    }

    function z() {
        h();
        It.over = true;
    }

    function O() {
        It.over = false;
    }

    function A(e) {
        1 == e.touches.length && "CANVAS" === e.target.nodeName && (It.down = true, Ft = K.offset(), Ft.left += 10, Ft.top -= $(window).scrollTop() - 10, It.x = (e.touches[0].pageX - Ft.left) / pt.scale, It.y = (e.touches[0].pageY - Ft.top) / pt.scale, p(e), e.preventDefault())
    }

    function P(e) {
        1 == e.touches.length && (e.preventDefault(), It.prev.x = It.x, It.prev.y = It.y, It.x = (e.touches[0].pageX - Ft.left) / pt.scale, It.y = (e.touches[0].pageY - Ft.top) / pt.scale, It.diff.x = It.x - It.prev.x, It.diff.y = It.y - It.prev.y)
    }

    function j() {
        It.down = false;
    }

    function N(e) {
        if (e || (e = window.event), yt > 4) {
            var t = sketch.Locale.string("alert-unsaved-statement");
            
            e.cancelBubble = true;
            e.returnValue = t;
            e.stopPropagation && (e.stopPropagation(), e.preventDefault());
            
            return t;
        }
    }

    function V() {
        setTimeout(function() {
            sketch.Social.initialize();
        }, 500);
        
        setTimeout(function() {
            sketch.Related.initialize();
        }, 500);
    }

    function _() {
        var e = 1250;
        $("html").hasClass("wide-scyscraper") && (e = 1330);
        
        var t = ut && (sketch.Util.isTouchDevice() || e > window.innerWidth);
        
        $("html").toggleClass("scyscrapes-below", t);
        ft.width = Math.max(window.innerWidth, et);
        ft.height = window.innerHeight;
        
        pt.scale = 1;
        pt.width = tt * pt.scale;
        pt.height = ot * pt.scale;
        
        W.width = pt.width;
        W.height = pt.height;
        
        Q.width(pt.width).height(pt.height);
        pt.x = K.position().left;
        pt.y = K.position().top;
        
        At.spinner.css({
            top: pt.y + (pt.height / 2 - 16)
        });
        
        At.toolbar.width(pt.width);
        
        $(".sketch-canvas-wrapper").css("width", t ? pt.width : "initial"), $(".sketch-footer").css({
            left: pt.x,
            width: pt.width
        });
    }

    function q(e) {
        e.preventDefault();
        var t = e.dataTransfer.files;
        if (t.length) {
            var o = new FileReader;
            o.onloadend = G;
            o.readAsDataURL(t[0]);
        }
    }

    function G(e) {
        e.target.result.match(/^data:image/gi) ? d(e.target.result) : alert("Doesn't seem like that's an image. Please try another file.");
    }

    function H(e) {
        n();
        $(document).on("mousemove", Y).on("mouseup", J);
        Y(e);
    }

    function Y(e) {
        var o = (e.clientX - At.replayControls.offset().left) / At.replayControls.width();
        t(o);
        e.preventDefault();
    }

    function J() {
        a();
        $(document).off("mousemove", Y).off("mouseup", J);
    }
    
    var W, X, K, Q, Z = {},
        et = 760,
        tt = 960,
        ot = 580,
        nt = 3,
        at = .7,
        it = 3,
        rt = "#000000",
        st = 50,
        ct = 6,
        lt = 4,
        ht = 20,
        dt = 2,
        ut = !(!$("#left-pillar").length || !$("#right-pillar").length),
        pt = {
            x: 0,
            y: 0,
            scale: 1,
            width: tt,
            height: ot
        },
        ft = {
            width: 0,
            height: 0
        },
        kt = [],
        gt = [],
        vt = [],
        mt = 0,
        wt = 0,
        bt = 0,
        yt = 0,
        xt = false,
        St = 0,
        Dt = 0,
        Lt = nt,
        Ct = at,
        Tt = rt,
        $t = it,
        Mt = 0,
        Et = 0,
        Ut = 0,
        Ft = {
            x: 0,
            y: 0
        },
        It = {
            x: 0,
            y: 0,
            prev: {
                x: 0,
                y: 0
            },
            diff: {
                x: 0,
                y: 0
            },
            press: {
                x: 0,
                y: 0
            },
            down: false,
            over: false
        },
        Rt = {
            spaceDown: false,
            leftDown: false,
            rightDown: false
        },
        Bt = false,
        zt = false,
        Ot = false,
        At = {
            toolbar: null,
            saveButton: null,
            resetButton: null,
            dashToggle: null,
            vibrationDropdown: null,
            sizeDropdown: null,
            facebookConnect: null
        };
    
    Z.initialize = function() {
    	Q = $(".sketch-canvas-container");
    	K = $(".sketch-canvas");
    	W = K.get(0);
    	At.spinner = $("#spinner");
    	At.toolbar = $(".toolbar");
    	At.saveButton = $(".toolbar .save-button");
    	At.undoButton = $(".toolbar .undo-button");
    	At.newButton = $(".toolbar .new-button");
    	At.resetButton = $(".toolbar .reset-button");
    	At.dashToggle = $(".toolbar .dash-toggle");
    	At.eraserToggle = $(".toolbar .eraser-toggle");
    	At.shareButton = $(".toolbar .share-button");
    	At.tweetButton = $(".toolbar .tweet-button");
    	At.replayControls = $(".replay-controls");
    	At.replayControlsProgress = $(".replay-controls .progress");
    	c();
    	s();
    	sketch.IO.initialize();
    	sketch.Locale.initialize();
    	
        if (W && W.getContext) {
            X = W.getContext("2d");
            W.addEventListener("mousedown", I, false);
            
            document.addEventListener("mousemove", R, false);
            document.addEventListener("mouseup", B, false);
            
            W.addEventListener("touchstart", A, false);
            W.addEventListener("touchmove", P, false);
            
            document.addEventListener("touchend", j, false);
            document.addEventListener("keydown", U, false);
            document.addEventListener("keyup", F, false);
            document.addEventListener("dragover", function(e) {
                e.preventDefault();
            }, false);
            
            document.addEventListener("dragenter", function(e) {
                e.preventDefault();
            }, false);
            
            document.addEventListener("dragexit", function(e) {
                e.preventDefault();
            }, false);
            
            document.addEventListener("drop", q, false);
            At.replayControls.on("mousedown", H);
            At.saveButton.on("click", x);
            At.shareButton.on("click", S);
            At.undoButton.on("click", D);
            At.newButton.on("click", C);
            At.resetButton.on("click", L);
            At.dashToggle.on("click", T);
            At.eraserToggle.on("click", M);
            At.tweetButton.on("click", E);
            window.addEventListener("resize", _, false);
            window.addEventListener("beforeunload", N, false);
            $(window).on("load", V);
            _();
            At.toolbar.css("visibility", "visible");
            sketch.Util.isTouchDevice() ? $("html").addClass("touch") : (K.on("mouseover", z), K.on("mouseout", O)), "undefined" != typeof chrome && chrome.app && chrome.app.isInstalled ? $("html").addClass("chrome-app-installed") : navigator.userAgent.match(/chrome/gi) && $("html").addClass("chrome-app-capable"), $("html").addClass("initialized"), g();
            
            var t = sketch.URL.readID();
            t.length >= 1 && e(t);
        }
    };
    
    Z.trackEvent = function(e, t, o, n, a) {
        _gaq.push(["_trackEvent", e, t, o, n, a]);
    };
    
    Z.displayError = function(e) {
        alert(e);
    };
    
    Z.getSketchShareURL = function() {
        return window.location.protocol + "//" + window.location.host + "/" + sketch.URL.readID();
    };
    
    Z.isEmpty = function() {
        return 0 === gt.length;
    };
    
    Z.linesToJSON = function() {
        for (var e = 0; gt.length > e; e++) 
        	gt[e] && gt[e].points && 0 != gt[e].points.length || (gt.splice(e, 1), e--);
        
        var t = "{";
        t += '"p":' + Mt.toFixed(6) + ",";
        t += '"a":' + Lt.toFixed(6) + ",";
        t += '"l":[';
        
        for (var e = 0; gt.length > e; e++) {
            var o = gt[e].points;
            t += "{";
            t += '"t":' + gt[e].thickness + ",";
            t += '"p":' + (0 == gt[e].perspective ? "0.000100" : gt[e].perspective.toFixed(6)) + ",";
            t += '"d":' + (gt[e].dashed ? 1 : 0) + ",";
            t += '"e":' + (gt[e].eraser ? 1 : 0) + ",";
            
            gt[e].color && "#000000" !== gt[e].color && (t += '"c":"' + gt[e].color + '",');
            t += '"points":[';
            
            for (var n = 0; o.length > n; n++) {
                var a = o[n],
                    i = Math.round(a.normal.x),
                    r = Math.round(a.normal.y);
                t += '"' + i + "x" + r + '"', t += o.length - 1 > n ? "," : ""
            }
            t += "]}";
            t += gt.length - 1 > e ? "," : ""
        }
        
        return t += "]}";
        
    };
    
    Z.saveSketch = function() {
        gt.length > 0 ? (i(), sketch.IO.saveSketch(), yt = 0) : alert("You need to draw something to save.");
    };
    
    Z.exportSketch = function() {
        Ut = 0;
        i();
        sketch.ShareOverlay.show();
        W.style.display = "none";
    };
    
    Z.getSketchAsImage = function() {
    	X.save();
    	X.globalCompositeOperation = "destination-over";
    	X.fillStyle = "#fff";
    	X.fillRect(0, 0, pt.width, pt.height);
    	X.restore();
    	
        return W.toDataURL("image/png");
    };
    
    Z.saveSketchAsImage = function() {
        var e = window.open("about:blank", "Your Sketch");
        e.document.write("<img src='" + Z.getSketchAsImage() + "' />");
    };
    
    Z.getSketchAsBlob = function() {
        var e = W.toDataURL("image/png");
        if (!e || !window.Blob || !window.atob) 
        	return null;
        
        var t, o = window.atob(e.split(",")[1]);
        
        n = e.split(",")[0].split(":")[1].split(";")[0];
        a = new ArrayBuffer(o.length);
        i = new Uint8Array(a);
        
        for (t = o.length; t--;) 
        	i[t] = o.charCodeAt(t);
        
        try {
            if (window.DataView) 
            	return new Blob([new DataView(a)], {
            		type: n
            	});
        } catch (r) {}
        
        try {
            return new Blob([i], {
                type: n
            });
        } catch (r) {}
        
        return null;
    };
    
    Z.injectSketch = function(e) {
        e.perspective && (Mt = e.perspective, Dt = e.perspective), e.amplitude && (Lt = e.amplitude, vibrationDropdown.setValue(Math.round(e.amplitude / nt))), vt = e.lines, wt = 0, mt = 0;
        for (var t = 0; vt.length > t; t++) {
            var n = vt[t].points;
            n && (mt += n.length);
        }
        o();
    }
    
    return Z;
}();

sketch.Main.initialize();